package com.example.mqttclient;

import androidx.appcompat.app.AppCompatActivity;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import androidx.core.app.NotificationCompat;
import com.example.mqttclient.mqtt.MqttService;
import com.example.mqttclient.protocol.AirConditioningMessage;
import com.example.mqttclient.protocol.BoolMessage;
import com.example.mqttclient.protocol.FloatMessage;
import com.example.mqttclient.protocol.IntMessage;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.Description;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.google.gson.Gson;
import org.eclipse.paho.client.mqttv3.MqttException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DevicesDemoActivity extends AppCompatActivity implements MqttService.MqttEventCallBack,
        CompoundButton.OnCheckedChangeListener {
    private TextView connectState, temperatureValue, humidityValue, pmValue, gasValue, doorStatus;
    private EditText airConditioningValue, addDeviceInput, removeDeviceInput;
    private MqttService.MqttBinder mqttBinder;
    private String TAG = "MainActivity";
    private Switch parlourLightSwitch, curtain_switch, fan_socket_switch, air_conditioning_switch;
    private Map<String, Integer> subscribeTopics = new HashMap<>();
    private Map<String, DeviceType> deviceTypes = new HashMap<>(); // 存储设备类型

    private enum DeviceType {
        TEMPERATURE, HUMIDITY, PM25, GAS, DOOR, LIGHT, FAN, CURTAIN, AIR_CONDITIONING
    }

    private LineChart temperatureChart, humidityChart, pmChart, gasChart;
    private List<Entry> temperatureEntries = new ArrayList<>();
    private List<Entry> humidityEntries = new ArrayList<>();
    private List<Entry> pmEntries = new ArrayList<>();
    private List<Entry> gasEntries = new ArrayList<>();
    private int dataIndex = 0;

    private ImageView temperatureArrow, humidityArrow, pmArrow, gasArrow;

    private Spinner parlourLightSpinner, fanSocketSpinner;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mqttBinder = (MqttService.MqttBinder) iBinder;
            mqttBinder.setMqttEventCallBack(DevicesDemoActivity.this);
            if (mqttBinder.isConnected()) {
                connectState.setText("已连接");
                subscribeTopics();
            } else {
                connectState.setText("未连接");
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_devices_demo);

        connectState = findViewById(R.id.dev_connect_state);

        Intent mqttServiceIntent = new Intent(this, MqttService.class);
        bindService(mqttServiceIntent, connection, Context.BIND_AUTO_CREATE);

        temperatureValue = findViewById(R.id.temperature_value);
        humidityValue = findViewById(R.id.humidity_value);
        pmValue = findViewById(R.id.pm_value);
        gasValue = findViewById(R.id.gas_value);
        doorStatus = findViewById(R.id.door_status);

        airConditioningValue = findViewById(R.id.air_conditioning_value);
        parlourLightSwitch = findViewById(R.id.parlour_light_switch);
        parlourLightSwitch.setOnCheckedChangeListener(this);
        curtain_switch = findViewById(R.id.curtain_switch);
        curtain_switch.setOnCheckedChangeListener(this);
        fan_socket_switch = findViewById(R.id.fan_socket_switch);
        fan_socket_switch.setOnCheckedChangeListener(this);
        air_conditioning_switch = findViewById(R.id.air_conditioning_switch);
        air_conditioning_switch.setOnCheckedChangeListener(this);

        temperatureChart = findViewById(R.id.temperature_chart);
        humidityChart = findViewById(R.id.humidity_chart);
        pmChart = findViewById(R.id.pm_chart);
        gasChart = findViewById(R.id.gas_chart);

        temperatureArrow = findViewById(R.id.temperature_arrow);
        humidityArrow = findViewById(R.id.humidity_arrow);
        pmArrow = findViewById(R.id.pm_arrow);
        gasArrow = findViewById(R.id.gas_arrow);

        temperatureArrow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                toggleChartVisibility(temperatureChart, temperatureArrow);
            }
        });
        humidityArrow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                toggleChartVisibility(humidityChart, humidityArrow);
            }
        });
        pmArrow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                toggleChartVisibility(pmChart, pmArrow);
            }
        });
        gasArrow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                toggleChartVisibility(gasChart, gasArrow);
            }
        });

        initChart(temperatureChart, "室内温度曲线图");
        initChart(humidityChart, "室内湿度曲线图");
        initChart(pmChart, "PM2.5 曲线图");
        initChart(gasChart, "可燃气体浓度曲线图");

        createNotificationChannel();

        parlourLightSpinner = findViewById(R.id.parlour_light_spinner);
        fanSocketSpinner = findViewById(R.id.fan_socket_spinner);

        ArrayAdapter<CharSequence> lightAdapter = ArrayAdapter.createFromResource(this,
                R.array.light_gear, android.R.layout.simple_spinner_item);
        lightAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        parlourLightSpinner.setAdapter(lightAdapter);

        ArrayAdapter<CharSequence> fanAdapter = ArrayAdapter.createFromResource(this,
                R.array.fan_gear, android.R.layout.simple_spinner_item);
        fanAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        fanSocketSpinner.setAdapter(fanAdapter);

        parlourLightSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                try {
                    mqttBinder.publishMessage("/test/light1/gear", new Gson().toJson(new IntMessage(position + 1)));
                } catch (MqttException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        fanSocketSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                try {
                    mqttBinder.publishMessage("/test/fan1/gear", new Gson().toJson(new IntMessage(position + 1)));
                } catch (MqttException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        // 找到添加和删除设备的按钮和输入框
        addDeviceInput = findViewById(R.id.add_device_input);
        removeDeviceInput = findViewById(R.id.remove_device_input);
        Button addDeviceButton = findViewById(R.id.add_device_button);
        Button deleteDeviceButton = findViewById(R.id.delete_device_button);

        // 设置点击事件监听器
        addDeviceButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String topic = addDeviceInput.getText().toString().trim();
                if (TextUtils.isEmpty(topic)) {
                    Toast.makeText(DevicesDemoActivity.this, "请输入设备主题", Toast.LENGTH_SHORT).show();
                    return;
                }

                if (subscribeTopics.containsKey(topic)) {
                    Toast.makeText(DevicesDemoActivity.this, "该设备已添加", Toast.LENGTH_SHORT).show();
                    return;
                }

                try {
                    // 根据主题模式判断设备类型
                    DeviceType type = determineDeviceType(topic);
                    deviceTypes.put(topic, type);

                    // 添加到订阅列表并订阅
                    subscribeTopics.put(topic, subscribeTopics.size() + 1);
                    mqttBinder.subscribe(topic);

                    Toast.makeText(DevicesDemoActivity.this, "设备添加成功", Toast.LENGTH_SHORT).show();
                    addDeviceInput.setText("");
                } catch (MqttException e) {
                    e.printStackTrace();
                    Toast.makeText(DevicesDemoActivity.this, "设备添加失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }
        });

        deleteDeviceButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String topic = removeDeviceInput.getText().toString().trim();
                if (TextUtils.isEmpty(topic)) {
                    Toast.makeText(DevicesDemoActivity.this, "请输入设备主题", Toast.LENGTH_SHORT).show();
                    return;
                }

                if (!subscribeTopics.containsKey(topic)) {
                    Toast.makeText(DevicesDemoActivity.this, "该设备不存在", Toast.LENGTH_SHORT).show();
                    return;
                }

                try {
                    // 从订阅列表移除并取消订阅
                    subscribeTopics.remove(topic);
                    deviceTypes.remove(topic);
                    mqttBinder.unSubscribe(topic);

                    Toast.makeText(DevicesDemoActivity.this, "设备删除成功", Toast.LENGTH_SHORT).show();
                    removeDeviceInput.setText("");
                } catch (MqttException e) {
                    e.printStackTrace();
                    Toast.makeText(DevicesDemoActivity.this, "设备删除失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    // 根据主题判断设备类型
    private DeviceType determineDeviceType(String topic) {
        if (topic.contains("temp")) return DeviceType.TEMPERATURE;
        if (topic.contains("hum")) return DeviceType.HUMIDITY;
        if (topic.contains("pm")) return DeviceType.PM25;
        if (topic.contains("gas")) return DeviceType.GAS;
        if (topic.contains("door")) return DeviceType.DOOR;
        if (topic.contains("light")) return DeviceType.LIGHT;
        if (topic.contains("fan")) return DeviceType.FAN;
        if (topic.contains("curtain")) return DeviceType.CURTAIN;
        if (topic.contains("air")) return DeviceType.AIR_CONDITIONING;
        return DeviceType.TEMPERATURE; // 默认温度设备
    }

    private void initChart(LineChart chart, String descriptionText) {
        Description description = new Description();
        description.setText(descriptionText);
        chart.setDescription(description);
        chart.getAxisRight().setEnabled(false);
    }

    private void toggleChartVisibility(LineChart chart, ImageView arrow) {
        if (chart.getVisibility() == View.GONE) {
            chart.setVisibility(View.VISIBLE);
            arrow.setImageResource(android.R.drawable.arrow_up_float);
        } else {
            chart.setVisibility(View.GONE);
            arrow.setImageResource(android.R.drawable.arrow_down_float);
        }
    }

    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
        switch (compoundButton.getId()) {
            case R.id.parlour_light_switch:
                try {
                    if (compoundButton.isChecked()) {
                        mqttBinder.publishMessage("/test/light1",
                                new Gson().toJson(new BoolMessage(true)));
                    } else {
                        mqttBinder.publishMessage("/test/light1",
                                new Gson().toJson(new BoolMessage(false)));
                    }
                } catch (MqttException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.curtain_switch:
                try {
                    if (compoundButton.isChecked()) {
                        mqttBinder.publishMessage("/test/curtain1",
                                new Gson().toJson(new BoolMessage(true)));
                    } else {
                        mqttBinder.publishMessage("/test/curtain1",
                                new Gson().toJson(new BoolMessage(false)));
                    }
                } catch (MqttException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.fan_socket_switch:
                try {
                    if (compoundButton.isChecked()) {
                        mqttBinder.publishMessage("/test/fan1",
                                new Gson().toJson(new BoolMessage(true)));
                    } else {
                        mqttBinder.publishMessage("/test/fan1",
                                new Gson().toJson(new BoolMessage(false)));
                    }
                } catch (MqttException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.air_conditioning_switch:
                try {
                    if (compoundButton.isChecked()) {
                        String json = new Gson().toJson(new AirConditioningMessage(true,
                                Float.parseFloat(airConditioningValue.getText().toString())));
                        Log.d("json", json);
                        mqttBinder.publishMessage("/test/airConditioning", json);
                    } else {
                        String json = new Gson().toJson(new AirConditioningMessage(false,
                                Float.parseFloat(airConditioningValue.getText().toString())));
                        Log.d("json", json);
                        mqttBinder.publishMessage("/test/airConditioning", json);
                    }
                } catch (MqttException e) {
                    e.printStackTrace();
                }
                break;
        }
    }

    void unSubscribeTopics() {
        try {
            for (Map.Entry<String, Integer> entry : subscribeTopics.entrySet()) {
                mqttBinder.unSubscribe(entry.getKey());
            }
            subscribeTopics.clear();
            deviceTypes.clear();
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onConnectSuccess() {
        subscribeTopics();
        connectState.setText("已连接");
    }

    @Override
    public void onConnectError(String error) {
        Log.d(TAG, "onConnectError: " + error);
        connectState.setText("未连接");
        subscribeTopics.clear();
        deviceTypes.clear();
    }

    @Override
    public void onDeliveryComplete() {
        Log.d(TAG, "publish ok");
    }

    @Override
    public void onMqttMessage(String topic, String message) {
        Log.d("onMqttMessage", "topic:" + topic + " message length:" + message.length() + " , message:" + message);
        Gson gson = new Gson();
        DeviceType type = deviceTypes.get(topic);
        if (type == null) return;

        try {
            switch (type) {
                case TEMPERATURE:
                    float temperature = gson.fromJson(message.trim(), FloatMessage.class).value;
                    temperatureValue.setText(String.valueOf(temperature));
                    updateChart(temperatureChart, temperatureEntries, temperature);
                    break;
                case HUMIDITY:
                    int humidity = gson.fromJson(message.trim(), IntMessage.class).value;
                    humidityValue.setText(String.valueOf(humidity));
                    updateChart(humidityChart, humidityEntries, humidity);
                    break;
                case PM25:
                    int pm = gson.fromJson(message.trim(), IntMessage.class).value;
                    pmValue.setText(String.valueOf(pm));
                    updateChart(pmChart, pmEntries, pm);
                    break;
                case GAS:
                    int gas = gson.fromJson(message.trim(), IntMessage.class).value;
                    gasValue.setText(String.valueOf(gas));
                    updateChart(gasChart, gasEntries, gas);
                    if (gas > 50) { // 假设可燃气体浓度超过50%LEL为过高
                        sendGasAlertNotification(gas);
                    }
                    break;
                case DOOR:
                    boolean doorOpen = gson.fromJson(message.trim(), BoolMessage.class).value;
                    String status = doorOpen ? "开" : "关";
                    doorStatus.setText(status);
                    break;
                // 可扩展处理其他类型设备的消息
            }
        } catch (Exception e) {
            Log.e(TAG, "解析MQTT消息失败: " + e.getMessage());
        }
    }

    private void updateChart(LineChart chart, List<Entry> entries, float value) {
        entries.add(new Entry(dataIndex++, value));
        LineDataSet dataSet = new LineDataSet(entries, "数据");
        dataSet.setColor(Color.BLUE);
        dataSet.setValueTextColor(Color.BLACK);
        LineData lineData = new LineData(dataSet);
        chart.setData(lineData);
        chart.invalidate();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        if (mqttBinder.isConnected()) {
            connectState.setText("已连接");
            subscribeTopics();
        } else {
            connectState.setText("未连接");
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        unSubscribeTopics();
    }

    @Override
    protected void onDestroy() {
        unbindService(connection);
        super.onDestroy();
    }

    void subscribeTopics() {
        try {
            // 订阅默认设备
            subscribeTopics.put("/test/temp", 1);
            deviceTypes.put("/test/temp", DeviceType.TEMPERATURE);

            subscribeTopics.put("/test/hum", 2);
            deviceTypes.put("/test/hum", DeviceType.HUMIDITY);

            subscribeTopics.put("/test/pm", 3);
            deviceTypes.put("/test/pm", DeviceType.PM25);

            subscribeTopics.put("/test/gas", 4);
            deviceTypes.put("/test/gas", DeviceType.GAS);

            subscribeTopics.put("/test/door", 5);
            deviceTypes.put("/test/door", DeviceType.DOOR);

            for (Map.Entry<String, Integer> entry : subscribeTopics.entrySet()) {
                mqttBinder.subscribe(entry.getKey());
            }
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = "GasAlertChannel";
            String description = "Channel for gas alert notifications";
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel channel = new NotificationChannel("gas_alert_channel", name, importance);
            channel.setDescription(description);
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }

    private void sendGasAlertNotification(int gasValue) {
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        Intent intent = new Intent(this, DevicesDemoActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "gas_alert_channel")
                .setSmallIcon(android.R.drawable.ic_dialog_alert)
                .setContentTitle("可燃气体浓度过高！")
                .setContentText("当前可燃气体浓度为 " + gasValue + "%LEL，请及时处理！")
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setContentIntent(pendingIntent)
                .setAutoCancel(true);

        Notification notification = builder.build();
        notificationManager.notify(1, notification);
    }
}